/**
 * Copyright (c) 2010-2011 Pierre Labatut
 *
 * This file is part of Space-Chronicles project.
 *
 * Space-Chronicles is free software: you can redistribute it and/or modify it
 * under the terms of its license which may be found in the accompanying
 * LICENSE file or <http://code.google.com/p/space-chronicles/>.
 */
package space.model;

import java.util.Arrays;
import java.util.Map;
import javax.media.opengl.GL3bc;
import jinngine.math.Matrix4;
import jinngine.physics.Body;
import space.debug.GlobalParameters;
import space.game.WldMaterial;
import space.gl.RenderContext;

import space.stream.StructureInput;

/**
 *
 * @author Pierre Labatut
 */
public class MdlObject implements Drawable {

    final String name;
    final Matrix4 matrix;
    final String materialName;
    final Drawable drawnMesh;
    final MdlObject engineGlow[];
    final MdlGeometry collisions[];
    final MdlEmpty childEmpties[];
    final MdlObject childs[];

    public MdlObject(StructureInput di) {
        name = di.readString();
        matrix = di.readObject(Matrix4.class);
        materialName = di.readString();
        drawnMesh = di.readObject(MdlMeshArray.class);
        engineGlow = di.readArray(MdlObject.class);
        collisions = di.readArray(MdlGeometry.class, new Class[]{Sphere.class, ConvexHull.class});
        childEmpties = di.readArray(MdlEmpty.class);
        childs = di.readArray(MdlObject.class);
    }

    private MdlObject(String name, Matrix4 matrix, String material, Drawable drawnMesh, MdlObject[] engineGlow,
            MdlGeometry[] collisions, MdlEmpty[] childEmpties, MdlObject[] childMeshes) {
        this.name = name;
        this.matrix = matrix;
        this.materialName = material;
        this.drawnMesh = drawnMesh;
        this.engineGlow = engineGlow;
        this.collisions = collisions;
        this.childs = childMeshes;
        this.childEmpties = childEmpties;
    }

    public Iterable<MdlEmpty> empties() {
        return Arrays.asList(childEmpties);
    }

    public Iterable<MdlObject> getChilds() {
        return Arrays.asList(childs);
    }

    public Matrix4 getMatrix() {
        return matrix;
    }

    public MdlObject optimize(GL3bc gl) {
        final Drawable spcMeshData = drawnMesh.optimize(gl);
        final MdlObject spcChildMeshes[] = new MdlObject[childs.length];
        for (int i = 0; i != childs.length; i++) {
            spcChildMeshes[i] = childs[i].optimize(gl);
        }
        final MdlObject spcGlowMeshes[] = new MdlObject[childs.length];
        for (int i = 0; i != engineGlow.length; i++) {
            spcGlowMeshes[i] = engineGlow[i].optimize(gl);
        }        
        return new MdlObject(name, matrix, materialName, spcMeshData, engineGlow,collisions,
                 childEmpties,spcChildMeshes);
    }

    public void draw(RenderContext rc) {
        rc.compose(matrix);
        drawnMesh.draw(rc.create());
        for (Drawable d : collisions) {
            d.draw(rc.create());
        }
        if (GlobalParameters.drawEmpties) {
            for (Drawable d : childEmpties) {
                d.draw(rc.create());
            }
        }
        for (Drawable d : childs) {
            d.draw(rc.create());
        }
    }

    public void dispose(GL3bc gl) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public Iterable<MdlGeometry> collision() {
        return Arrays.asList(collisions);
    }

    public Drawable representation() {
        return drawnMesh;
    }

    public void addGeometry(Body body) {
        for (MdlGeometry md : collisions) {
            md.addGeometry(body);
        }
    }

    public WldMaterial material(Map<String, WldMaterial> materialLib) {
        return materialLib.get(materialName);
    }

    public Iterable<MdlObject> getEngineGlow() {
        return Arrays.asList(engineGlow);
    }
}
